package com.yelobblog.yelobblog.service.impl;

import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.yelobblog.yelobblog.common.exception.ApiException;
import com.yelobblog.yelobblog.common.untils.ThreadLocalUtil;
import com.yelobblog.yelobblog.common.untils.userStatusEnum;
import com.yelobblog.yelobblog.domain.entity.agent;
import com.yelobblog.yelobblog.domain.entity.dialogue;
import com.yelobblog.yelobblog.domain.entity.dialogueGroup;
import com.yelobblog.yelobblog.mapper.agentMapper;
import com.yelobblog.yelobblog.service.agentService;
import jakarta.annotation.Resource;
import org.springframework.stereotype.Service;
import com.yelobblog.yelobblog.common.exception.ErrorEnum;
import org.springframework.web.reactive.function.BodyInserters;
import org.springframework.web.reactive.function.client.WebClient;
import reactor.core.publisher.Flux;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;

import java.util.HashMap;
import java.util.Map;
import com.yelobblog.yelobblog.domain.Vo.dialogueGroupVo;

@Service
public class agentServiceimpl implements agentService {
    @Resource
    private agentMapper agentMapper;
    private static final ObjectMapper objectMapper = new ObjectMapper();
    private static final String key = "***";
    private static final String url = "https://api.qnaigc.com/v1/chat/completions";

    private final WebClient webClient = WebClient.create();
    @Override
    public Page<agent> getAgentList(Integer pageNum, Integer pageSize) {
        return agentMapper.getAgentList(new Page<>(pageNum, pageSize),1);
    }
    @Override
    public agent getAgentById(Integer id) {
        return agentMapper.getAgentById(id);
    }

    @Override
    public Page<agent> getAgentByUserId(Integer userId, Integer pageNum, Integer pageSize) {
        return agentMapper.getAgentByUserId(new Page<>(pageNum, pageSize),userId);
    }

    @Override
    public void addAgent(agent agent) {
        Map<String, Object> claims = ThreadLocalUtil.get();
        Integer role = (Integer) claims.get("role");
        if(role.equals(userStatusEnum.NORMAL.getCode())){
            throw new ApiException(ErrorEnum.PERMISSION_DENIED.getErrorCode(),ErrorEnum.PERMISSION_DENIED.getErrorMsg());
        }
        Integer userId = (Integer) claims.get("id");
        agent.setUserId(userId);
        agentMapper.addAgent(agent);
    }
    @Override
    public void updateAgent(agent agent) {
        Map<String, Object> claims = ThreadLocalUtil.get();
        Integer role = (Integer) claims.get("role");
        if(role.equals(userStatusEnum.NORMAL.getCode())){
            throw new ApiException(ErrorEnum.PERMISSION_DENIED.getErrorCode(),ErrorEnum.PERMISSION_DENIED.getErrorMsg());
        }
        Integer userId = (Integer) claims.get("id");
        if (!userId.equals(agent.getUserId())) {
            throw new ApiException(ErrorEnum.PERMISSION_DENIED.getErrorCode(),ErrorEnum.PERMISSION_DENIED.getErrorMsg());
        }
        agentMapper.updateAgent(agent);
    }

    @Override
    public Page<dialogueGroupVo> getDialogueGroupByAgentId(Integer agentId, Integer pageNum, Integer pageSize) {
        Map<String,Object> claims= ThreadLocalUtil.get();
        Integer userId = (Integer) claims.get("id");
        return agentMapper.getDialogueGroupByAgentId(new Page<>(pageNum, pageSize),agentId,userId);
    }
    @Override
    public Integer addDialogueGroup(dialogueGroup dialogueGroup) {
        Map<String, Object> claims = ThreadLocalUtil.get();
        Integer role = (Integer) claims.get("role");
        if(role.equals(userStatusEnum.NORMAL.getCode())){
            throw new ApiException(ErrorEnum.PERMISSION_DENIED.getErrorCode(),ErrorEnum.PERMISSION_DENIED.getErrorMsg());
        }
        Integer userId = (Integer) claims.get("id");
        dialogueGroup.setUserId(userId);
        agentMapper.addDialogueGroup(dialogueGroup);
        return  dialogueGroup.getId();
    }
    @Override
    public void deleteDialogueGroup(Integer id) {
        Map<String, Object> claims = ThreadLocalUtil.get();
        Integer userId = (Integer) claims.get("id");
        Integer uId= agentMapper.getUserIdOfDialogueGroupById(id);
        if (uId == null||!uId.equals(userId)) {
            throw new ApiException(ErrorEnum.PERMISSION_DENIED.getErrorCode(),ErrorEnum.PERMISSION_DENIED.getErrorMsg());
        }
        agentMapper.deleteDialogueGroup(id);
    }
    @Override
    public Page<dialogue> getDialogueByGroupId(Integer groupId, Integer pageNum, Integer pageSize) {
        return agentMapper.getDialogueByGroupId(new Page<>(pageNum, pageSize),groupId);
    }
    @Override
    public void addDialogue(String content, Integer groupId) {
        Map<String, Object> claims = ThreadLocalUtil.get();
        Integer role = (Integer) claims.get("role");
        if(role.equals(userStatusEnum.NORMAL.getCode())){
            throw new ApiException(ErrorEnum.PERMISSION_DENIED.getErrorCode(),ErrorEnum.PERMISSION_DENIED.getErrorMsg());
        }
        Integer userId = (Integer) claims.get("id");
        agentMapper.addDialogue(content, userId, groupId);
    }
    @Override
    public Flux<String> handleAiRequest(String prompt, Integer groupId) {
        Map<String, Object> claims = ThreadLocalUtil.get();
        Integer userId = (Integer) claims.get("id");

        if (prompt == null || prompt.isEmpty()) {
            return Flux.error(new IllegalArgumentException("Prompt is required"));
        }
        Page<dialogue> dialoguePage= agentMapper.getDialogueByGroupId(new Page<>(1, 4),groupId);

        Map<String, Object> message = new HashMap<>();
        Map<String, Object> data = new HashMap<>();

        Integer agentId = agentMapper.getAgentIdByGroupId(groupId);
//        data.put("role","system");
        agent agent = agentMapper.getAgentById(agentId);
        Map<String, Object> systemMessage = new HashMap<>();
        systemMessage.put("role","system");
        systemMessage.put("content",agent.getAgentDesc());
        data.computeIfAbsent("messages", k -> new java.util.ArrayList<>());
        ((java.util.ArrayList<Map<String, Object>>) data.get("messages")).add(systemMessage);

//        data.put("content",agent.getAgentDesc());
        for (dialogue dialogue : dialoguePage.getRecords()) {
            String content = dialogue.getContent();
            try {
                // 解析 JSON 字符串
                JsonNode jsonNode = objectMapper.readTree(content);
                JsonNode userNode = jsonNode.get("user");
                JsonNode assistantNode = jsonNode.get("assistant");
                if (userNode != null) {
                    // 处理 user 部分
                    String userContent = userNode.asText();
                    // 可以将 user 消息添加到 messages 列表中
                    Map<String, Object> userMessage = new HashMap<>();
                    userMessage.put("role", "user");
                    userMessage.put("content", userContent);
                    // 假设存在一个 messages 列表来存储历史消息
                    data.computeIfAbsent("messages", k -> new java.util.ArrayList<>());
                    ((java.util.ArrayList<Map<String, Object>>) data.get("messages")).add(userMessage);
                }

                if (assistantNode != null) {
                    // 处理 assistant 部分
                    String assistantContent = assistantNode.asText();
                    // 可以将 assistant 消息添加到 messages 列表中
                    Map<String, Object> assistantMessage = new HashMap<>();
                    assistantMessage.put("role", "assistant");
                    assistantMessage.put("content", assistantContent);
                    data.computeIfAbsent("messages", k -> new java.util.ArrayList<>());
                    ((java.util.ArrayList<Map<String, Object>>) data.get("messages")).add(assistantMessage);
                }
            } catch (Exception e) {
                // 处理解析异常
                System.err.println("Error parsing dialogue content: " + e.getMessage());
            }
        }
        message.put("role", "user");
        message.put("content", prompt);

        data.computeIfAbsent("messages", k -> new java.util.ArrayList<>());
        ((java.util.ArrayList<Map<String, Object>>) data.get("messages")).add(message);
        data.put("model", "deepseek-v3");
        data.put("stream", true);

        StringBuilder loadMessage = new StringBuilder("{\"user\":\"" + prompt + "\",\"assistant\":\"");

        return webClient.post()
                .uri(url)
                .header("Authorization", "Bearer " + key)
                .header("Content-Type", "application/json")
                .body(BodyInserters.fromValue(data))
                .retrieve()
                .bodyToFlux(String.class)
                .flatMap(chunk -> {
                    String[] lines = chunk.split("\n");
                    return Flux.fromArray(lines)
                            .filter(line -> !line.isEmpty())
                            .map(line -> {
                                try {
                                    // 解析 JSON
                                    if(line.equals("[DONE]")){
                                        return "";
                                    }
                                    JsonNode rootNode = objectMapper.readTree(line);
                                    JsonNode choicesNode = rootNode.path("choices");
                                    if (!choicesNode.isEmpty() && choicesNode.isArray()) {
                                        JsonNode firstChoice = choicesNode.get(0);
                                        JsonNode deltaNode = firstChoice.path("delta");
                                        JsonNode contentNode = deltaNode.path("content");
                                        if (!contentNode.isMissingNode()) {
                                            String content = contentNode.asText();
                                            // 转义特殊字符后再追加
                                            loadMessage.append(escapeJson(content));
//                                            System.out.println(content);
                                            Map<String, String> msgMap = new HashMap<>();
                                            msgMap.put("msg", content);
                                            // 将 Map 转换为 JSON 字符
                                            return objectMapper.writeValueAsString(msgMap);
                                        }
                                    }
                                } catch (Exception e) {
                                    // 处理异常
                                    System.err.println("Error parsing JSON: " + e.getMessage());
                                }
                                return "";
                            });
                })
//                .concatWith(Flux.just(loadMessage.append("\"}").toString()))
                .doOnComplete(() -> {
                    // 打印 loadMessage 的最终结果
                    loadMessage.append("\"}");
                    try {
                        // 将 loadMessage 字符串解析为 Map
                        Map<String, String> messageMap = objectMapper.readValue(loadMessage.toString(), Map.class);
                        // 将 Map 转换为标准的 JSON 字符串
                        String jsonString = objectMapper.writeValueAsString(messageMap);
                        System.out.println(jsonString);
                        agentMapper.addDialogue(jsonString, userId, groupId);
                    } catch (Exception e) {
                        System.err.println("Error converting loadMessage to JSON: " + e.getMessage());
                    }
                });
    }

    private String escapeJson(String input) {
        if (input == null) {
            return "";
        }
        StringBuilder sb = new StringBuilder();
        for (int i = 0; i < input.length(); i++) {
            char ch = input.charAt(i);
            switch (ch) {
                case '"':
                    sb.append("\\\"");
                    break;
                case '\\':
                    sb.append("\\\\");
                    break;
                case '\b':
                    sb.append("\\b");
                    break;
                case '\f':
                    sb.append("\\f");
                    break;
                case '\n':
                    sb.append("\\n");
                    break;
                case '\r':
                    sb.append("\\r");
                    break;
                case '\t':
                    sb.append("\\t");
                    break;
                default:
                    // 范围在 0x00 - 0x1F 之间的控制字符需要转义
                    if (ch <= 0x1F) {
                        String ss = Integer.toHexString(ch);
                        sb.append("\\u");
                        for (int k = 0; k < 4 - ss.length(); k++) {
                            sb.append('0');
                        }
                        sb.append(ss.toUpperCase());
                    } else {
                        sb.append(ch);
                    }
            }
        }
        return sb.toString();
    }

}
